const { request } = require('../../utils/request');
const { PASS_SCORE, TOKEN_STORAGE_KEY } = require('../../config');
const pageBehavior = require('../../utils/pageBehavior');
const StateManager = require('../../utils/state');
const { smartNavigate } = require('../../utils/navigation');

const DISPLAY_TYPE_MAP = {
  single: '单选题',
  multiple: '多选题',
  judge: '判断题'
};

const parseNumber = (value, fallback) => {
  if (typeof value === 'number' && !Number.isNaN(value)) {
    return value;
  }
  if (typeof value === 'string' && value.trim() !== '') {
    const num = Number(value);
    if (!Number.isNaN(num)) {
      return num;
    }
  }
  return fallback;
};

const toNullableNumber = (value) => {
  if (value === null || value === undefined) {
    return null;
  }
  const num = Number(value);
  if (Number.isNaN(num)) {
    return null;
  }
  return num;
};

const normalizeQuestion = (raw) => {
  const type = (raw?.type || raw?.questionType || 'single').toLowerCase();
  let options = raw?.options;
  if (typeof options === 'string') {
    try {
      options = JSON.parse(options);
    } catch (error) {
      options = [];
    }
  }
  if (!Array.isArray(options)) {
    options = [];
  }
  const normalizedOptions = options.map((opt, idx) => {
    if (typeof opt === 'string') {
      return { value: String(opt), text: opt };
    }
    const value =
      opt.value !== undefined
        ? opt.value
        : opt.id !== undefined
        ? opt.id
        : idx;
    const text = opt.text || opt.label || opt.content || String(value);
    const description = opt.description || opt.desc || '';
    return {
      value: String(value),
      text,
      description
    };
  });

  if (type === 'judge' && normalizedOptions.length === 0) {
    normalizedOptions.push({ value: 'true', text: '正确' });
    normalizedOptions.push({ value: 'false', text: '错误' });
  }

  return {
    id: raw?.id,
    question: raw?.question || raw?.title || '',
    options: normalizedOptions,
    type,
    displayType: DISPLAY_TYPE_MAP[type] || raw?.displayType || '',
    score: parseNumber(raw?.score, 0),
    correctAnswers: raw?.correctAnswers || raw?.answers || raw?.answer || null,
    hint: raw?.hint || ''
  };
};

Page({
  behaviors: [pageBehavior],

  data: {
    submitting: false,
    mode: 'exam',
    paper: {},
    questions: [],
    currentQuestion: null,
    showQuestion: true,
    devPaperMode: false,
    answers: {},
    currentIndex: 0,
    progress: 0,
    bestScore: null,
    remainingAttempts: 0,
    result: {},
    countdown: {
      seconds: 0,
      running: false
    }
  },

  // 判断是否为前端开发模拟登录
  isDevMode() {
    try {
      const devConfig = require('../../config/dev');
      const token = wx.getStorageSync(TOKEN_STORAGE_KEY);
      return !!(devConfig && devConfig.enabled && token && String(token).startsWith('dev_token_'));
    } catch (e) {
      return false;
    }
  },

  // 是否启用了开发模式（不要求 dev_token_）
  isDevEnabled() {
    try {
      const devConfig = require('../../config/dev');
      return !!(devConfig && devConfig.enabled);
    } catch (e) {
      return false;
    }
  },

  // 本地开发模式试卷数据
  buildDevPaperData() {
    return {
      title: '入学测验（开发模式）',
      passScore: PASS_SCORE,
      maxAttempts: -1,
      durationSeconds: 0,
      countdownWarnAt: 90,
      countdownDangerAt: 30,
      questions: [
        {
          id: 'q1',
          question: '学校图书馆每天几点开门？',
          type: 'single',
          options: [
            { id: 'A', text: '6:30' },
            { id: 'B', text: '7:00' },
            { id: 'C', text: '7:30' },
            { id: 'D', text: '8:00' }
          ],
          score: 10,
          correctAnswers: 'B'
        },
        {
          id: 'q2',
          question: '以下哪些属于校内常用服务？',
          type: 'multiple',
          options: [
            { id: 'A', text: '校园网认证' },
            { id: 'B', text: '医疗门诊' },
            { id: 'C', text: '体育馆预约' },
            { id: 'D', text: '学费缴纳' }
          ],
          score: 10,
          correctAnswers: ['A', 'C', 'D']
        },
        {
          id: 'q3',
          question: '入学教育考试需要在规定时间内完成。',
          type: 'judge',
          options: [],
          score: 10,
          correctAnswers: 'true'
        }
      ]
    };
  },

  // 本地评测得分
  evaluateDevScore(questions, answers) {
    let score = 0;
    questions.forEach((q) => {
      const correct = q.correctAnswers;
      const my = answers[q.id];
      if (q.type === 'multiple') {
        const a = Array.isArray(my) ? my.map(String).sort().join(',') : '';
        const b = Array.isArray(correct) ? correct.map(String).sort().join(',') : '';
        if (a && a === b) score += Number(q.score || 0);
      } else {
        if (String(my) !== '' && String(my) === String(
          Array.isArray(correct) ? correct[0] : correct
        )) {
          score += Number(q.score || 0);
        }
      }
    });
    return score;
  },

  async onLoad() {
    // 检查认证状态，如果未认证则跳转登录
    if (!this.requireAuth()) {
      return;
    }
    await this.bootstrap();
  },

  async bootstrap() {
    this.setData({
      submitting: false,
      mode: 'exam',
      result: {},
      currentIndex: 0,
      progress: 0,
      devPaperMode: false,
      countdown: Object.assign({}, this.data.countdown, { running: false })
    });

    await this.executeAsync(async () => {
      try {
        const [paperRes, resultRes] = await Promise.all([
          request({ url: '/api/miniapp/quiz/paper', method: 'GET' }),
          request({ url: '/api/miniapp/quiz/result', method: 'GET', showErrorToast: false }).catch(() => null)
        ]);

        const paperRaw = paperRes?.data || {};
        const resultRaw = resultRes?.data || {};

        const passScore = parseNumber(paperRaw.passScore, PASS_SCORE);
        const questions = (paperRaw.questions || [])
          .map((q) => normalizeQuestion(q))
          .filter((q) => q.id && q.options.length);

        if (!questions.length) {
          this.setError('当前没有可用试卷，请稍后重试');
          return;
        }

        const maxAttempts = parseNumber(paperRaw.maxAttempts, -1);
        const attemptsUsed = Math.max(0, parseNumber(resultRaw.attemptsUsed, 0));
        const remainingAttempts =
          maxAttempts >= 0 ? Math.max(0, maxAttempts - attemptsUsed) : 9999;

        const durationSeconds = this.extractDuration(paperRaw);

        this.setData({
          paper: {
            title: paperRaw.title || '新生入学测验',
            passScore,
            maxAttempts,
            durationSeconds,
            countdownWarnAt: parseNumber(paperRaw.countdownWarnAt, 90),
            countdownDangerAt: parseNumber(paperRaw.countdownDangerAt, 30)
          },
          questions,
          currentQuestion: questions[0] || null,
          devPaperMode: false,
          answers: this.buildInitialAnswers(questions),
          bestScore: toNullableNumber(resultRaw.bestScore),
          remainingAttempts,
          currentIndex: 0,
          progress: this.computeProgress(0, questions.length),
          countdown: {
            seconds: durationSeconds,
            running: durationSeconds > 0
          }
        });
      } catch (e) {
        if (!this.isDevEnabled()) {
          throw e;
        }
        const devPaper = this.buildDevPaperData();
        const passScore = parseNumber(devPaper.passScore, PASS_SCORE);
        const questions = (devPaper.questions || [])
          .map((q) => normalizeQuestion(q))
          .filter((q) => q.id && q.options.length);
        const durationSeconds = this.extractDuration(devPaper);
        this.setData({
          paper: {
            title: devPaper.title || '新生入学测验',
            passScore,
            maxAttempts: parseNumber(devPaper.maxAttempts, -1),
            durationSeconds,
            countdownWarnAt: parseNumber(devPaper.countdownWarnAt, 90),
            countdownDangerAt: parseNumber(devPaper.countdownDangerAt, 30)
          },
          questions,
          currentQuestion: questions[0] || null,
          devPaperMode: true,
          answers: this.buildInitialAnswers(questions),
          bestScore: null,
          remainingAttempts: 9999,
          currentIndex: 0,
          progress: this.computeProgress(0, questions.length),
          countdown: {
            seconds: durationSeconds,
            running: durationSeconds > 0
          }
        });
      }
    }, {
      showLoading: true,
      showError: true,
      defaultMessage: '试卷加载失败，请稍后重试'
    });
  },

  extractDuration(paperRaw) {
    const durationSeconds = parseNumber(paperRaw.durationSeconds, 0);
    if (durationSeconds > 0) {
      return durationSeconds;
    }
    const duration = parseNumber(paperRaw.duration, 0);
    if (duration > 0) {
      return duration > 3600 ? duration : duration * 60;
    }
    const timeLimit = parseNumber(paperRaw.timeLimit, 0);
    return timeLimit > 0 ? timeLimit : 0;
  },

  buildInitialAnswers(questions) {
    const answers = {};
    questions.forEach((q) => {
      if (q.type === 'multiple') {
        answers[q.id] = [];
      } else {
        answers[q.id] = '';
      }
    });
    return answers;
  },

  computeProgress(index, total) {
    if (!total) {
      return 0;
    }
    return Math.min(100, Math.round(((index + 1) / total) * 100));
  },

  onAnswerChange(event) {
    const questionId = event.detail?.questionId;
    const value = event.detail?.value;
    if (!questionId) {
      return;
    }
    this.setData({
      [`answers.${questionId}`]: value
    });
  },

  goPrev() {
    const nextIndex = Math.max(0, this.data.currentIndex - 1);
    this.updateCurrentIndex(nextIndex);
  },

  goNext() {
    const nextIndex = Math.min(this.data.questions.length - 1, this.data.currentIndex + 1);
    this.updateCurrentIndex(nextIndex);
    // iOS 某些版本需要延迟一次强制布局
    setTimeout(() => {
      this.setData({}); // 触发一次微更新，确保旧节点被回收
    }, 0);
  },

  handlePrimaryAction() {
    if (this.data.currentIndex === this.data.questions.length - 1) {
      this.submitExam();
    } else {
      this.goNext();
    }
  },

  updateCurrentIndex(index) {
    const nextQuestion = this.data.questions[index] || null;
    // 通过隐藏后再显示，强制销毁并重建题目组件，避免 iOS 残影
    this.setData({ showQuestion: false }, () => {
      this.setData({
        currentIndex: index,
        progress: this.computeProgress(index, this.data.questions.length),
        currentQuestion: nextQuestion,
        showQuestion: true
      });
    });
  },

  // 移除滑动事件，改为按钮切换覆盖当前题

  hasAnswered(question) {
    const answer = this.data.answers[question.id];
    if (question.type === 'multiple') {
      return Array.isArray(answer) && answer.length > 0;
    }
    return answer !== undefined && answer !== null && String(answer) !== '';
  },

  async submitExam(autoSubmit = false) {
    if (this.data.submitting) {
      return;
    }
    if (this.data.remainingAttempts <= 0) {
      this.showError('已无可用次数');
      return;
    }

    if (!autoSubmit) {
      const unanswered = this.data.questions.filter((q) => !this.hasAnswered(q));
      if (unanswered.length) {
        this.showError('仍有题目未作答');
        return;
      }
    }

    this.setData({ submitting: true });
    StateManager.showLoading({ title: autoSubmit ? '时间到，正在提交' : '提交中...' });
    try {
      if (this.isDevMode() || this.data.devPaperMode) {
        const score = this.evaluateDevScore(this.data.questions, this.data.answers);
        const passScore = this.data.paper.passScore || PASS_SCORE;
        const passed = score >= passScore;
        const remainingAttempts =
          this.data.remainingAttempts > 0 ? this.data.remainingAttempts - 1 : 9998;
        const bestScore =
          this.data.bestScore !== null ? Math.max(this.data.bestScore, score) : score;

        const result = this.composeResult({
          score,
          passed,
          passScore,
          remainingAttempts,
          bestScore
        });

        this.setData({
          mode: 'result',
          result,
          remainingAttempts,
          bestScore,
          submitting: false,
          countdown: Object.assign({}, this.data.countdown, { running: false })
        });
        return;
      }

      const payload = this.data.questions.map((question) => {
        const answer = this.data.answers[question.id];
        if (question.type === 'multiple') {
          return {
            questionId: question.id,
            answer: Array.isArray(answer) ? answer : []
          };
        }
        return {
          questionId: question.id,
          answer: answer ?? ''
        };
      });

      const res = await request({
        url: '/api/miniapp/quiz/submit',
        method: 'POST',
        data: { answers: payload }
      });

      const data = res?.data || {};
      const score = toNullableNumber(data.score);
      const passScore = this.data.paper.passScore || PASS_SCORE;
      const passed =
        data.passed !== undefined ? !!data.passed : score !== null ? score >= passScore : false;
      const remainingAttempts = parseNumber(
        data.remainingAttempts,
        this.data.remainingAttempts > 0 ? this.data.remainingAttempts - 1 : 0
      );
      const bestScore = toNullableNumber(
        data.bestScore !== undefined ? data.bestScore : this.data.bestScore
      );

      const result = this.composeResult({
        score,
        passed,
        passScore,
        remainingAttempts,
        bestScore
      });

      this.setData({
        mode: 'result',
        result,
        remainingAttempts,
        bestScore,
        submitting: false,
        countdown: Object.assign({}, this.data.countdown, { running: false })
      });
    } catch (error) {
      this.setData({ submitting: false });
    } finally {
      StateManager.hideLoading();
    }
  },

  composeResult({ score, passed, passScore, remainingAttempts, bestScore }) {
    const status = passed ? 'success' : 'error';
    const title = passed ? '恭喜通过入学测验' : '尚未通过及格线';
    const description = passed
      ? '你已完成入学测验，可以继续查看时间轴与入学指南。'
      : `及格线为 ${passScore} 分，可在剩余次数内重新答题。`;
    const meta =
      bestScore !== null
        ? `历史最高成绩：${bestScore} 分`
        : `本次成绩：${score !== null ? score : '--'} 分`;

    return {
      status,
      title,
      description,
      score: score !== null ? score : 0,
      meta,
      primaryText: remainingAttempts > 0 ? '重新答题' : '',
      secondaryText: '返回首页',
      extra: `剩余次数：${remainingAttempts >= 9999 ? '不限' : remainingAttempts} 次`
    };
  },

  restart() {
    if (this.data.submitting) {
      return;
    }
    if (this.data.remainingAttempts <= 0) {
      this.showError('已无可用次数');
      return;
    }
    this.bootstrap();
  },

  returnHome() {
    smartNavigate('/pages/index/index');
  },

  handleCountdownFinish() {
    if (this.data.mode !== 'exam' || this.data.submitting) {
      return;
    }
    this.showError('答题时间已结束');
    this.submitExam(true);
  }
});
